function Person () {this.run = 'run'}
Person.prototype.name = 'Nicholas'
Person.prototype.age = 29
Person.prototype.job = 'soft'
Person.prototype.sayName = function () {
  console.log(this.name)
}
var person1 = new Person()
person1.sayName() // Nicholas
var person2 = new Person()
person2.sayName() // Nicholas
console.log(person2.sayName == person1.sayName) // true 因为对象是同一个原型，同一个sayName

// 修改一个原型属性，看另一个是否改变
person1.__proto__.name = 'lee'
console.log(person2.name) // lee  改变了。说明原型只有一个

// hasOwnProperty()  如果属性存在与于实例中，则返回true
console.log(person2.hasOwnProperty('age')) // false
console.log(person2.hasOwnProperty('run')) // true

// 验证函数原型的constructor指向这个函数 直接调用跟new操作符调用
function Desk () {
  this.name = 'lee'
  console.log(arguments.callee == Desk.prototype.constructor) // true
}
Desk() // true

// // 
var desk = new Desk() // true

// 实例的__proto__指向构造函数原型
console.log(desk.__proto__ === Desk.prototype) // true
// console.log(Array.prototype.toString.call([1, 2])) // 1,2
// // 因为原型是共享的，所以Object的原型上的方法，也被Desk共享
// console.log(Desk.prototype.toString.call([1, 2])) // [object Array]


function Box () {
  this.name = 'lee'
}
Box.prototype = { 
  // 这种方式去写原型，会将原型覆盖，判断 constructor 会出现误差，判断为 Object
  // 最好加 constructor 属性
  age: 26,
  constructor: Box
}

var box = new Box()

console.log(box.__proto__) // {age: 26, __proto__: Object}

console.log(box.__proto__.__proto__) //Object 原型方法组成的对象

// 上面的现象说明，Object 的原型，存在于 Box 的原型。由于这种原型的嵌套关系。
// 根据原型查找方法或者属性的习惯做大胆的推断，当我们
// 想调用 Object 的原型方法时，直接用 Box 来调用，都是行的通得！！
// 比如我们经常拿来判断类型的常用方法 Object.prototype.toString()
var kind = Box.prototype.__proto__.toString()
console.log(kind) // [object Object]  没打印出【object Box】就对了。这里判断的是类型
// 而不是构造函数
var kind2 = Box.prototype.toString()

console.log(kind2) // 相同的效果，读取 toString 方法时，沿着原型向上找，找到了 Object 的方法

// 其实这当中存在着问题，因为 方法都是直接或者间接通过 Object.prototypr 调用的
// this 的指向始终都是 Object,也就是始终会将 Object 转化为字符串输出。想打印出真正正确的结果
// 还得改变下 this 的指向，不能老是代指 Object
var kind3 = Box.prototype.toString.call([1, 2, 3])

console.log(kind3) // [object Array]

// 要想获得对象或者原型的构造函数，直接拿 constructor 属性就行(判断类型就别用constructor了，
// 拿到了一个自定义的构造函数，到最后还是不知道属于那一种基本类型)
console.log(box.constructor == Box) // true
console.log(box.constructor === Box.prototype.constructor) // true
